package com.hfi.security.browser.session;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.hfi.security.core.exception.ErrorCode;
import com.hfi.security.core.properties.SecurityProperties;
import com.hfi.security.core.support.Response;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.security.web.DefaultRedirectStrategy;
import org.springframework.security.web.RedirectStrategy;
import org.springframework.security.web.session.InvalidSessionStrategy;
import org.springframework.security.web.util.UrlUtils;
import org.springframework.util.Assert;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @author ChangLiang
 * @date 2019/8/29
 */
public class HfiInvalidSessionStrategy implements InvalidSessionStrategy {

    private Logger logger = LoggerFactory.getLogger(getClass());

    /**
     * 重定向策略
     */
    private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();

    private ObjectMapper objectMapper = new ObjectMapper();

    /**
     * 系统配置信息
     */
    private SecurityProperties securityProperties;

    /**
     * 跳转前是否创建新的session
     * 如果不配置 会由于session失效导致不断在onValidSessionDetected重定向
     */
    private boolean createNewSession = true;

    public HfiInvalidSessionStrategy(SecurityProperties securityProperties) {
        String sessionInvalidUrl = securityProperties.getBrowser().getSession().getSessionInvalidUrl();
        Assert.isTrue(UrlUtils.isValidRedirectUrl(sessionInvalidUrl),"url must start with '/' or with 'http(s)'");
        Assert.isTrue(StringUtils.endsWithIgnoreCase(sessionInvalidUrl,".html"),"url must end with '.html'");
        this.securityProperties = securityProperties;
    }


    @Override
    public void onInvalidSessionDetected(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
        logger.info("session失效");

        if (createNewSession) {
            request.getSession();
        }

        String sourceUrl = request.getRequestURI();
        String targetUrl;

        if (StringUtils.endsWithIgnoreCase(sourceUrl, ".html")) {
            if (StringUtils.equals(sourceUrl, securityProperties.getBrowser().getLoginPage())) {
                targetUrl = sourceUrl;
            } else {
                targetUrl = securityProperties.getBrowser().getSession().getSessionInvalidUrl();
            }
            logger.info("跳转到:"+targetUrl);
            redirectStrategy.sendRedirect(request, response, targetUrl);
        } else {
            Response resp = sessionInvalid();
            response.setStatus(HttpStatus.UNAUTHORIZED.value());
            response.setContentType("application/json;charset=UTF-8");
            response.getWriter().write(objectMapper.writeValueAsString(resp));
        }
    }

    private Response sessionInvalid(){
        String message = "session失效";
        Response resp = new Response();
        resp.setErrorcode(ErrorCode.NO_AUTHENTICATION.value);
        resp.setValue(message+"validMsg:访问的服务需要身份认证，请引导用户到登录页");
        return resp;
    }
}
